package com.bjsxt.httpclient;

import com.bjsxt.httpclient.pojo.User;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

/*
* 使用main方法，测试httpClient技术
* */
public class TestHttpClient {
    public static void main(String[] args) throws Exception {
//        testGetNoParams();
//        testGetParams();
        testPost();
    }
    /*
    * POST请求
    * */
    public static void testPost() throws Exception{
        /*
        * 无参数post请求
        * */
//        创建http客户端。
        HttpClient client = HttpClients.createDefault();
//        创建请求地址
        HttpPost post = new HttpPost("http://localhost/test");
//        发起请求
        HttpResponse response=client.execute(post);
        System.out.println(EntityUtils.toString(response.getEntity(),"UTF-8"));
        /*
        * 有参数post请求
        * */
//        请求头传递参数，和get请求携带参数的方式一致。
        URIBuilder builder = new URIBuilder("http://localhost/params");
        builder.addParameter("name","post");
        builder.addParameter("password","postPassword");
        HttpResponse postResponse = client.execute(new HttpPost(builder.build()));
        System.out.println(EntityUtils.toString(postResponse.getEntity(),"UTF-8"));

//        请求体传递参数
        HttpPost bodyParamsPost = new HttpPost("http://localhost/bodyParams");
//        定义请求协议体，设置请求参数。使用请求体传递参数的时候，需要定义请求体格式，默认是表单格式。
//        使用URIBuilder构建的URI对象，就是请求体传递参数的。
        User user = new User();
        user.setName("name1");
        user.setPassword("password1");
        User user1 = new User();
        user1.setName("name2");
        user1.setPassword("password2");
/*
* 把集合users对象----》JSON字符串
* */
        List<User> users = new ArrayList<>();
        users.add(user);
        users.add(user1);
//        把集合users----》JSON字符串
        ObjectMapper objectMapper = new ObjectMapper();
        //创建Json的转换器对象。

        String paramsString=objectMapper.writeValueAsString(users);
        //java对象转换成JSON格式字符串。
        /*
        * 补充：
        *    property  -类型中getter和setter的命名，去除set/get，剩余部分首字母转小写。
        *       <bean><property name="abc"></property></bean>
        *    field -类型中定义的实例变量。
        *       String name ;
        *
        * */

//        拼接一个json格式字符串，表示请求参数，一个List<User>，注：这个toString方法重写过。
//        String paramsString = "["+user.toString()+","+user1.toString()+"]";
//        过时但是还能用。有二个方法可以替代。
        HttpEntity entity = new StringEntity(paramsString,"application/json","UTF-8");
        bodyParamsPost.setEntity(entity);
/*
* 字符串转化为java对象。
* */
        String responseString=EntityUtils.toString(client.execute(bodyParamsPost).getEntity(),"UTF-8");

        String userString = responseString.substring(1,responseString.indexOf("},")+1);

        User responseUser = objectMapper.readValue(userString,User.class);

        System.out.println(responseUser+"!!!");
//        构建一个Jackson识别的Java类型映射。
        JavaType valueType=
                objectMapper.getTypeFactory().constructType(List.class,User.class);
        List<User> responseList = objectMapper.readValue(responseString,valueType);
        System.out.println(responseList+"？？？");

    }
    /*
    * 有参数GET请求
    * */
    public static void testGetParams() throws URISyntaxException, IOException {
        HttpClient client = HttpClients.createDefault();
//        基于Builder，构建请求地址
        URIBuilder builder = new URIBuilder("http://localhost/params");
//        基于单参数传递，构建请求地址
        builder.addParameter("name","bjsxt");
        builder.addParameter("password","admin123");
//        请求统一资源路径
        URI uri = builder.build();

//        基于多参数传递，构建请求地址。
        List<NameValuePair> nvps = new ArrayList<>();
        nvps.add(new BasicNameValuePair("name","bjsxt"));
        nvps.add(new BasicNameValuePair("password","admin123"));
        builder.addParameters(nvps);
//        构建路径
        URI uri1 = builder.build();

//        输出路径
        System.out.println(uri1.toASCIIString());

//        发送请求
        String result = EntityUtils.toString(client.execute(new HttpGet(uri1)).getEntity());
        System.out.println(result);
    }

    /*
    * 无参数GET请求
    * 使用浏览器，访问网站的过程：
    * 1、打开浏览器
    * 2、输入地址
    * 3、访问
    * 4、看结果
    * 使用httpClient，访问WEB服务的过程：
    * 1、创建客户端，相当于打开浏览器
    * 2、创建请求地址，相当于输入地址
    * 3、发起请求，相当于访问网站（回车键）
    * 4、处理响应结果，相当于浏览器显示结果
    * */
    public static void testGetNoParams() throws IOException {
        //创建客户端对象，相当于打开了浏览器
        HttpClient client = HttpClients.createDefault();
        //创建请求地址,相当于输入地址
        HttpGet get = new HttpGet("http://localhost:80/test");
        //发起请求，接收响应对象
        HttpResponse httpResponse= client.execute(get);
        //获取响应体，响应数据是一个基于HTTP协议标准字符串封装的对象。
        //所以，响应体和响应头，都是封装的HTTP协议数据。
        //直接使用可能有乱码和解析错误----》转换。
        HttpEntity entity =httpResponse.getEntity();
        //协议转换,通过http实体工具类，转换响应体数据，使用的字符集是UTF-8
        String responseString=EntityUtils.toString(entity,"UTF-8");

        System.out.println("服务器响应的数据时：["+responseString+"]");

        //关闭客户端对象，相当于关闭浏览器。回收资源
        client =null;
    }
}
